package de.uni_potsdam.hpi.bpt.ai.diagram;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.util.FileCopyUtils;

public class StencilSetFactory {
	
	protected String stencilSetPath = "resources" + File.separator + "stencilsets";
	protected Map<String, String> NS2FN = new HashMap<String,String>();
	
	protected Map<String, StencilSet> stencilsets = new HashMap<String, StencilSet>();
	private static StencilSetFactory factory = null;
	
	/**
	 * Singleton constructor
	 */
	protected StencilSetFactory() { // Singleton
		NS2FN.put("http://b3mn.org/stencilset/bpmn2.0#",  "bpmn2.0.json");
		NS2FN.put("http://b3mn.org/stencilset/bpmn1.1#",  "bpmn1.1.json");
		NS2FN.put("http://b3mn.org/stencilset/epc#",      "epc.json");
		NS2FN.put("http://b3mn.org/stencilset/petrinet#", "petrinet.json");
	}
	
	/**
	 * Returns the Singleton object of this factory
	 * 
	 * @return
	 */
	public static StencilSetFactory getInstance() {
		if (null == factory) {
			factory = new StencilSetFactory();
		}
		
		return factory;
	}
	
	/**
	 * Returns a StencilSet for the given namespace
	 * 
	 * @param namespace
	 * @return
	 * @throws IOException 
	 * @throws JSONException 
	 * @throws FileNotFoundException 
	 * @throws UnsupportedEncodingException 
	 */
	public StencilSet getStencilSet(String namespace) throws UnsupportedEncodingException, FileNotFoundException, JSONException, IOException {
		if (!this.stencilsets.containsKey(namespace)) {
			this.loadStencilSet(namespace);
		}
		return this.stencilsets.get(namespace);
	}
	
	/**
	 * Loads a StencilSet specification (copied from Oryx) and creates a TencilSet that is aware of this specification 
	 * 
	 * @param namespace
	 * @throws UnsupportedEncodingException
	 * @throws FileNotFoundException
	 * @throws JSONException
	 * @throws IOException
	 */
	protected void loadStencilSet(String namespace) throws UnsupportedEncodingException, FileNotFoundException, JSONException, IOException {
		String ssFilename = this.stencilSetPath + File.separator + this.NS2FN.get(namespace);
		File ssfile = new File(ssFilename);
		if(!ssfile.exists()) {
			this.stencilsets.put(namespace, new StencilSet(namespace));
		}
		else {
			JSONObject specification = new JSONObject(readFileToString(ssfile)); 
			this.stencilsets.put(namespace, new StencilSet(namespace, specification));
		}
	}
	
	/**
	 * Reads a stencilset specification (JSON, UTF8 encoded) into a String and returns it
	 * 
	 * @param file
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private String readFileToString(File file) throws UnsupportedEncodingException, FileNotFoundException, IOException {
		return FileCopyUtils.copyToString(new InputStreamReader(new FileInputStream(file), "UTF-8"));
	}
	public void setStencilSetPath(String stencilSetPath) {
		this.stencilSetPath = stencilSetPath;
	}
	public String getStencilSetPath() {
		return stencilSetPath;
	}
}
